package com.feng.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.feng.Exception.SystemException;
import com.feng.domain.ResponseResult;
import com.feng.domain.entity.LoginUser;
import com.feng.domain.entity.User;
import com.feng.domain.enums.AppHttpCodeEnum;
import com.feng.domain.vo.BlogUserLoginVo;
import com.feng.domain.vo.UserInfoVo;
import com.feng.service.BlogLoginService;
import com.feng.service.UserService;
import com.feng.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.ParameterResolutionDelegate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class BlogLoginServiceImpl implements BlogLoginService {
    //需要要securtiyConfig进行装入bean容器
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserService userService;
    @Override
    public ResponseResult login(User user) {
        //该类为Authenticate的实现类，传入用户的账号密码
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
        //进行认证，会调用userDetailService进行用户认证，默认认证方式是内存进行查询
        // 所以我们需要重写一个方法，使其实现userDetailService类，让其从数据库进行查询认证，此项目调用UserDetailsServiceImpl
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //判断是否认证通过
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        //获取userid生成token
        LoginUser loginUser= (LoginUser) authenticate.getPrincipal();
        Long id = loginUser.getUser().getId();
        String userid = id.toString();
        String jwt = JwtUtil.createJWT(userid);
        //把用户信息存入redis
        redisCache.setCacheObject("bloglogin:"+userid,loginUser);
        //把token与userInfo封装并返回
        BlogUserLoginVo blogUserLoginVo=new BlogUserLoginVo();
        //把user拷贝为userInfo
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);
        blogUserLoginVo.setToken(jwt);
        blogUserLoginVo.setUserInfo(userInfoVo);


        return ResponseResult.okResult(blogUserLoginVo);
    }

    @Override
    public ResponseResult logout() {
        //之前在认证过滤器时已经将loginuser对象存入SecurityContextHolder
//        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        //获取userid
//        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
//        Long id = loginUser.getUser().getId();
        Long userId = SecurityUtils.getUserId();

        //删除reids用户信息
        redisCache.deleteObject("bloglogin:"+userId);
        //将对象从线程池移除
        UserThreadLocal.remove();
        return ResponseResult.okResult();
    }
   @Transactional
    @Override
    public ResponseResult faget(String phone, String password, String code) {
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        if(!StringUtils.hasText(phone)||!StringUtils.hasText(password)){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_PHONENOTNULL);
        }
        if(!StringUtils.hasText(code)){
            throw new SystemException(AppHttpCodeEnum.CODE_EXPIRE);
        }
        //根据手机号条件查询
        queryWrapper.eq(User::getEmail,phone);
        User user = userService.getOne(queryWrapper);
        if(ObjectUtils.isEmpty(user)){
            //用户不存在
            throw new SystemException(AppHttpCodeEnum.USER_NOT);
        }
        //判断验证码是否一致
        String codes =  redisTemplate.opsForValue().get(phone);
        if(codes==null){
            throw  new SystemException(AppHttpCodeEnum.CODE_EXPIRES);
        }
        if(!codes.equals(code)){
            throw new SystemException(AppHttpCodeEnum.CODE_ERROR);
        }

        String encode = passwordEncoder.encode(password);
        //重置默认密码为123456
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User :: getId, user.getId());
        updateWrapper.set(User :: getPassword,encode);

        userService.update(updateWrapper);
        return ResponseResult.okResult(user.getUserName());

    }
}
